package top.hongsheng9527.bookdownload.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import top.hongsheng9527.bookdownload.core.crawl.CrawlParser;
import top.hongsheng9527.bookdownload.core.crawl.RuleBean;
import top.hongsheng9527.bookdownload.mapper.*;
import top.hongsheng9527.bookdownload.service.CrawlService;
import top.hongsheng9527.bookdownload.utils.*;
import top.hongsheng9527.bookdownload.vo.*;
import top.hongsheng9527.bookdownload.vo.CrawlSource;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Wanghs
 * @create 2022/4/8
 * @description
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CrawlServiceImpl implements CrawlService {
    @Value("${current.save-path}")
    private String SAVE_PATH;
    @Resource
    private CrawlSourceDao crawlSourceDao;

    public static ExecutorService newFixedThreadPool = null;

    @Override
    public void addCrawlSource(CrawlSource source) {
        Date currentDate = new Date();
        source.setCreateTime(currentDate);
        source.setUpdateTime(currentDate);
        crawlSourceDao.saveCrawlSource(source);
    }

    @Override
    public CrawlSource listCrawlByPage(String address) {
        CrawlSource crawlSource = crawlSourceDao.getCrawlSourceList(address);
        return crawlSource;
    }

    @Override
    public CrawlSource queryCrawlSource(Integer sourceId) {
        return crawlSourceDao.selectCrawlSource(sourceId);
    }

    @Override
    public void addCrawlSingleTask(CrawlSingleTask singleTask) {
        // Asynchronous call
        bootDbProxy(singleTask, SAVE_PATH);
    }

    @Async
    public void bootDbProxy(CrawlSingleTask singleTask, String SAVE_PATH) {
        newFixedThreadPool = Executors.newCachedThreadPool();
        newFixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                log.info("The program starts to execute the collection task thread...");
                while (true) {
                    CrawlSingleTask task;
                    try {
                        task = singleTask;
                        if (task != null) {
                            // Query crawler rules
                            CrawlSource source = queryCrawlSource(task.getSourceId());
                            RuleBean ruleBean = new ObjectMapper().readValue(source.getCrawlRule(), RuleBean.class);
                            if (parseBookAndSave(task, ruleBean, SAVE_PATH)) {
                                // Acquisition succeeded
                                log.info("\n Download complete~~~~~~~~~");
                            }
                        }
                        //休眠1分钟
                        TimeUnit.MINUTES.sleep(1);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                    break;
                }
            }
        });
    }


    @Override
    public boolean parseBookAndSave(CrawlSingleTask task, RuleBean ruleBean, String SAVE_PATH) {
        int catId = task.getCatId();
        Integer sourceId = task.getSourceId();
        String bookId = task.getSourceBookId();
        final AtomicBoolean parseResult = new AtomicBoolean(false);
        Book book = new Book();
        book.setBookName(task.getBookName());
        book.setAuthorName(task.getAuthorName());
        book.setCatId(catId);
        if (catId == 7) {
            //女频
            book.setWorkDirection((byte) 1);
        } else {
            //男频
            book.setWorkDirection((byte) 0);
        }
        book.setCrawlBookId(bookId);
        book.setCrawlSourceId(sourceId);
        book.setCrawlLastTime(new Date());
        book.setId(new IdWorker().nextId());
        //解析章节目录
        CrawlParser.parseBookIndexAndContent(bookId, book, ruleBean, SAVE_PATH);
        parseResult.set(true);
        return parseResult.get();
    }
}
